--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Node / ReticulumProjects / MeshChatX.git / files / meshchatx / src / frontend / js / rnode / Capabilities.js
Displaying Raw • Download
meshchatx/src/frontend/js/rnode/Capabilities.js e0f1f99cd1c208c5008a936230c38e448dddd45d (e0f1f99c) Text, 6.70 KB
T8b949e/**
* Runtime capability detection for RNode flasher.
*
* Determines which connection transports are available in the current
* environment (Web Serial, Web Bluetooth, WebUSB polyfill, WiFi/HTTP)
* and exposes structured reasons when something is unsupported so the UI
* can render actionable guidance.
*
* Pure functions, no DOM mutation, safe to import in tests.
*/
Tff7b72export Tff7b72const Te6edf3TRANSPORT_SERIAL Tff7b72= Ta5d6ff"serial"Tb4b4b4;
Tff7b72export Tff7b72const Te6edf3TRANSPORT_BLUETOOTH Tff7b72= Ta5d6ff"bluetooth"Tb4b4b4;
Tff7b72export Tff7b72const Te6edf3TRANSPORT_WIFI Tff7b72= Ta5d6ff"wifi"Tb4b4b4;
Tff7b72const Te6edf3ANDROID_RE Tff7b72= Ta5d6ff/android/iTb4b4b4;
Tff7b72const Te6edf3ELECTRON_RE Tff7b72= Ta5d6ff/electron/iTb4b4b4;
Tff7b72function Te6edf3pickGlobalTb4b4b4(Te6edf3providedTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3providedTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3providedTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72typeof Tffa657window Tff7b72!== Ta5d6ff"undefined"Tb4b4b4) Tb4b4b4{
Tff7b72return Tffa657windowTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Tff7b72typeof Tffa657globalThis Tff7b72!== Ta5d6ff"undefined"Tb4b4b4) Tb4b4b4{
Tff7b72return Tffa657globalThisTb4b4b4;
Tb4b4b4}
Tff7b72return Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3detectPlatformTb4b4b4(Te6edf3envTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3ua Tff7b72= Te6edf3envTb4b4b4.Te6edf3navigatorTff7b72?Tb4b4b4.Te6edf3userAgent Tff7b72?? Ta5d6ff""Tb4b4b4;
Tff7b72const Te6edf3isAndroid Tff7b72= Te6edf3ANDROID_RETb4b4b4.Te6edf3testTb4b4b4(Te6edf3uaTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3isElectron Tff7b72= Te6edf3ELECTRON_RETb4b4b4.Te6edf3testTb4b4b4(Te6edf3uaTb4b4b4) Tff7b72|| Tffa657BooleanTb4b4b4(Te6edf3envTb4b4b4.Te6edf3electronTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3hasMeshChatXAndroid Tff7b72= Tffa657BooleanTb4b4b4(Te6edf3envTb4b4b4.Te6edf3MeshChatXAndroidTb4b4b4)Tb4b4b4;
Tff7b72return Tb4b4b4{
Te6edf3isAndroidTb4b4b4,
Te6edf3isElectronTb4b4b4,
Te6edf3hasMeshChatXAndroidTb4b4b4,
Te6edf3isSecureContextTff7b72: Tffa657BooleanTb4b4b4(Te6edf3envTb4b4b4.Te6edf3isSecureContextTb4b4b4)Tb4b4b4,
Te6edf3userAgentTff7b72: Te6edf3uaTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3detectSerialTb4b4b4(Te6edf3envTb4b4b4, Te6edf3platformTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3hasNative Tff7b72= Tffa657BooleanTb4b4b4(Te6edf3envTb4b4b4.Te6edf3navigatorTff7b72?Tb4b4b4.Te6edf3serialTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3hasUsbPolyfillTarget Tff7b72= Tffa657BooleanTb4b4b4(Te6edf3envTb4b4b4.Te6edf3navigatorTff7b72?Tb4b4b4.Te6edf3usbTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3hasPolyfillModule Tff7b72= Tffa657BooleanTb4b4b4(Te6edf3envTb4b4b4.Te6edf3serialTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3hasNativeFlasher Tff7b72=
Tffa657BooleanTb4b4b4(Te6edf3envTb4b4b4.Te6edf3MeshChatXAndroidTb4b4b4)
Tff7b72&& Tff7b72typeof Te6edf3envTb4b4b4.Te6edf3MeshChatXAndroidTb4b4b4.Te6edf3hasNativeRNodeFlasher Tff7b72=== Ta5d6ff"function"
Tff7b72&& Tffa657BooleanTb4b4b4(Te6edf3envTb4b4b4.Te6edf3MeshChatXAndroidTb4b4b4.Te6edf3hasNativeRNodeFlasherTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3hasNativeFlasherTb4b4b4) Tb4b4b4{
Tff7b72return Tb4b4b4{
Te6edf3availableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3kindTff7b72: Ta5d6ff"android-native-activity"Tb4b4b4,
Te6edf3polyfilledTff7b72: Tff7b72falseTb4b4b4,
Te6edf3reasonTff7b72: Tff7b72nullTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3hasNativeTb4b4b4) Tb4b4b4{
Tff7b72return Tb4b4b4{
Te6edf3availableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3kindTff7b72: Ta5d6ff"native"Tb4b4b4,
Te6edf3polyfilledTff7b72: Tff7b72falseTb4b4b4,
Te6edf3reasonTff7b72: Tff7b72nullTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3hasUsbPolyfillTarget Tff7b72&& Te6edf3hasPolyfillModuleTb4b4b4) Tb4b4b4{
Tff7b72return Tb4b4b4{
Te6edf3availableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3kindTff7b72: Ta5d6ff"polyfill"Tb4b4b4,
Te6edf3polyfilledTff7b72: Tff7b72trueTb4b4b4,
Te6edf3reasonTff7b72: Tff7b72nullTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3hasUsbPolyfillTarget Tff7b72&& Tff7b72!Te6edf3hasPolyfillModuleTb4b4b4) Tb4b4b4{
Tff7b72return Tb4b4b4{
Te6edf3availableTff7b72: Tff7b72falseTb4b4b4,
Te6edf3kindTff7b72: Ta5d6ff"polyfill-pending"Tb4b4b4,
Te6edf3polyfilledTff7b72: Tff7b72falseTb4b4b4,
Te6edf3reasonTff7b72: Ta5d6ff"polyfill_not_loaded"Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3platformTb4b4b4.Te6edf3isAndroidTb4b4b4) Tb4b4b4{
Tff7b72return Tb4b4b4{
Te6edf3availableTff7b72: Tff7b72falseTb4b4b4,
Te6edf3kindTff7b72: Ta5d6ff"none"Tb4b4b4,
Te6edf3polyfilledTff7b72: Tff7b72falseTb4b4b4,
Te6edf3reasonTff7b72: Ta5d6ff"android_webview_no_serial"Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72return Tb4b4b4{
Te6edf3availableTff7b72: Tff7b72falseTb4b4b4,
Te6edf3kindTff7b72: Ta5d6ff"none"Tb4b4b4,
Te6edf3polyfilledTff7b72: Tff7b72falseTb4b4b4,
Te6edf3reasonTff7b72: Ta5d6ff"browser_unsupported"Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3detectBluetoothTb4b4b4(Te6edf3envTb4b4b4, Te6edf3platformTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3hasNative Tff7b72= Tffa657BooleanTb4b4b4(Te6edf3envTb4b4b4.Te6edf3navigatorTff7b72?Tb4b4b4.Te6edf3bluetoothTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3hasNativeTb4b4b4) Tb4b4b4{
Tff7b72return Tb4b4b4{
Te6edf3availableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3kindTff7b72: Ta5d6ff"web-bluetooth"Tb4b4b4,
Te6edf3reasonTff7b72: Tff7b72nullTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3platformTb4b4b4.Te6edf3hasMeshChatXAndroidTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3bridge Tff7b72= Te6edf3envTb4b4b4.Te6edf3MeshChatXAndroidTb4b4b4;
Tff7b72const Te6edf3hasPerms Tff7b72=
Tff7b72typeof Te6edf3bridgeTff7b72?Tb4b4b4.Te6edf3hasBluetoothPermissions Tff7b72=== Ta5d6ff"function"
Tff7b72? Tffa657BooleanTb4b4b4(Te6edf3bridgeTb4b4b4.Te6edf3hasBluetoothPermissionsTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72: Tff7b72falseTb4b4b4;
Tff7b72return Tb4b4b4{
T8b949e// WebView still has no Web Bluetooth GATT. Permissions matter for
T8b949e// mesh RNode BLE and OS pairing. Keep transport disabled for flash
T8b949e// selection, but surface a clearer reason + actions.
Te6edf3availableTff7b72: Tff7b72falseTb4b4b4,
Te6edf3kindTff7b72: Ta5d6ff"android-bridge"Tb4b4b4,
Te6edf3reasonTff7b72: Te6edf3hasPerms
Tff7b72? Ta5d6ff"android_bridge_no_web_bluetooth"
Tff7b72: Ta5d6ff"android_bluetooth_permission_required"Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72return Tb4b4b4{
Te6edf3availableTff7b72: Tff7b72falseTb4b4b4,
Te6edf3kindTff7b72: Ta5d6ff"none"Tb4b4b4,
Te6edf3reasonTff7b72: Te6edf3platformTb4b4b4.Te6edf3isSecureContext Tff7b72? Ta5d6ff"browser_unsupported" Tff7b72: Ta5d6ff"insecure_context"Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
Tff7b72function Te6edf3detectWifiTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72return Tb4b4b4{
Te6edf3availableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3kindTff7b72: Ta5d6ff"http"Tb4b4b4,
Te6edf3reasonTff7b72: Tff7b72nullTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}
T8b949e/**
* Inspect the environment and return a capabilities snapshot.
*
* @param {object} [overrides]
* @param {object} [overrides.env] alternative global object (window-like) for tests
* @returns {{
* platform: object,
* transports: { serial: object, bluetooth: object, wifi: object },
* anyAvailable: boolean,
* }}
*/
Tff7b72export Tff7b72function Te6edf3detectCapabilitiesTb4b4b4(Te6edf3overrides Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3env Tff7b72= Te6edf3pickGlobalTb4b4b4(Te6edf3overridesTb4b4b4.Te6edf3envTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3platform Tff7b72= Te6edf3detectPlatformTb4b4b4(Te6edf3envTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3transports Tff7b72= Tb4b4b4{
Tb4b4b4[Te6edf3TRANSPORT_SERIALTb4b4b4]Tff7b72: Te6edf3detectSerialTb4b4b4(Te6edf3envTb4b4b4, Te6edf3platformTb4b4b4)Tb4b4b4,
Tb4b4b4[Te6edf3TRANSPORT_BLUETOOTHTb4b4b4]Tff7b72: Te6edf3detectBluetoothTb4b4b4(Te6edf3envTb4b4b4, Te6edf3platformTb4b4b4)Tb4b4b4,
Tb4b4b4[Te6edf3TRANSPORT_WIFITb4b4b4]Tff7b72: Te6edf3detectWifiTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3anyAvailable Tff7b72=
Te6edf3transportsTb4b4b4[Te6edf3TRANSPORT_SERIALTb4b4b4]Tb4b4b4.Te6edf3available Tff7b72||
Te6edf3transportsTb4b4b4[Te6edf3TRANSPORT_BLUETOOTHTb4b4b4]Tb4b4b4.Te6edf3available Tff7b72||
Te6edf3transportsTb4b4b4[Te6edf3TRANSPORT_WIFITb4b4b4]Tb4b4b4.Te6edf3availableTb4b4b4;
Tff7b72return Tb4b4b4{ Te6edf3platformTb4b4b4, Te6edf3transportsTb4b4b4, Te6edf3anyAvailable Tb4b4b4}Tb4b4b4;
Tb4b4b4}
T8b949e/**
* Choose the most appropriate default transport given current capabilities.
*
* Order of preference: native serial, polyfill serial, web bluetooth, wifi.
*/
Tff7b72export Tff7b72function Te6edf3pickDefaultTransportTb4b4b4(Te6edf3capabilitiesTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3t Tff7b72= Te6edf3capabilitiesTff7b72?Tb4b4b4.Te6edf3transports Tff7b72?? Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3tTb4b4b4[Te6edf3TRANSPORT_SERIALTb4b4b4]Tff7b72?Tb4b4b4.Te6edf3availableTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3TRANSPORT_SERIALTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3tTb4b4b4[Te6edf3TRANSPORT_BLUETOOTHTb4b4b4]Tff7b72?Tb4b4b4.Te6edf3availableTb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3TRANSPORT_BLUETOOTHTb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3TRANSPORT_WIFITb4b4b4;
Tb4b4b4}
T8b949e/**
* Return a list of human-readable, translation-aware suggestions for a
* transport that is unavailable. The caller maps these keys to i18n strings.
*/
Tff7b72export Tff7b72function Te6edf3transportSuggestionKeysTb4b4b4(Te6edf3capabilitiesTb4b4b4, Te6edf3transportNameTb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3transport Tff7b72= Te6edf3capabilitiesTff7b72?Tb4b4b4.Te6edf3transportsTff7b72?Tb4b4b4.Tb4b4b4[Te6edf3transportNameTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3transport Tff7b72|| Te6edf3transportTb4b4b4.Te6edf3availableTb4b4b4) Tb4b4b4{
Tff7b72return Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3platform Tff7b72= Te6edf3capabilitiesTb4b4b4.Te6edf3platform Tff7b72?? Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3reason Tff7b72= Te6edf3transportTb4b4b4.Te6edf3reason Tff7b72?? Ta5d6ff"unknown"Tb4b4b4;
Tff7b72const Te6edf3suggestions Tff7b72= Tb4b4b4[Ta5d6ff`Ta5d6fftools.rnode_flasher.support.Tffd700${Te6edf3transportNameTffd700}Ta5d6ff.Tffd700${Te6edf3reasonTffd700}Ta5d6ff`Tb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3transportName Tff7b72=== Te6edf3TRANSPORT_SERIAL Tff7b72&& Te6edf3platformTb4b4b4.Te6edf3isAndroidTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3reason Tff7b72=== Ta5d6ff"android_webview_no_serial"Tb4b4b4) Tb4b4b4{
Te6edf3suggestionsTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff"tools.rnode_flasher.support.serial.android_use_chrome"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3transportName Tff7b72=== Te6edf3TRANSPORT_SERIAL Tff7b72&& Te6edf3reason Tff7b72=== Ta5d6ff"android_permission_required"Tb4b4b4) Tb4b4b4{
Te6edf3suggestionsTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff"tools.rnode_flasher.support.serial.android_request_usb"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3transportName Tff7b72=== Te6edf3TRANSPORT_BLUETOOTH Tff7b72&& Tff7b72!Te6edf3platformTb4b4b4.Te6edf3isSecureContextTb4b4b4) Tb4b4b4{
Te6edf3suggestionsTb4b4b4.Te6edf3pushTb4b4b4(Ta5d6ff"tools.rnode_flasher.support.bluetooth.requires_https"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72return Te6edf3suggestionsTb4b4b4;
Tb4b4b4}
Tff7b72export Tff7b72default Tb4b4b4{
Te6edf3detectCapabilitiesTb4b4b4,
Te6edf3pickDefaultTransportTb4b4b4,
Te6edf3transportSuggestionKeysTb4b4b4,
Te6edf3TRANSPORT_SERIALTb4b4b4,
Te6edf3TRANSPORT_BLUETOOTHTb4b4b4,
Te6edf3TRANSPORT_WIFITb4b4b4,
Tb4b4b4}Tb4b4b4;
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────